package simpledb;
import java.io.IOException;
import java.util.*;

/**
 * Inserts tuples read from the child operator into
 * the tableid specified in the constructor
 */
public class Insert extends AbstractDbIterator {

    TransactionId  transactionId  ;
    DbIterator dbIterator  ;
    int tableid ;
    Tuple resultTuple ;


    /**
     * Constructor.
     * @param t The transaction running the insert.
     * @param child The child operator from which to read tuples to be inserted.
     * @param tableid The table in which to insert tuples.
     * @throws DbException if TupleDesc of child differs from table into which we are to insert.
     */
    public Insert(TransactionId t, DbIterator child, int tableid)
        throws DbException {
        // some code goes here

        this.transactionId = t ;
        this.dbIterator = child ;
        this.tableid = tableid ;

        Type types[] = new Type[]{ Type.INT_TYPE };
        TupleDesc tupleDesc  = new TupleDesc( types );
        resultTuple = new Tuple( tupleDesc ) ;
    }

    public TupleDesc getTupleDesc() {
        // some code goes here

        return resultTuple.getTupleDesc() ;
    }

    public void open() throws DbException, TransactionAbortedException {
        // some code goes here

        this.dbIterator.open();

    }

    public void close() {
        // some code goes here
        this.dbIterator.close();
    }

    public void rewind() throws DbException, TransactionAbortedException {
        // some code goes here

        this.dbIterator.rewind();
    }

    boolean isFirstCalled = true ;

    /**
     * Inserts tuples read from child into the tableid specified by the
     * constructor. It returns a one field tuple containing the number of
     * inserted records. Inserts should be passed through BufferPool.
     * An instances of BufferPool is available via Database.getBufferPool().
     * Note that insert DOES NOT need check to see if a particular tuple is
     * a duplicate before inserting it.
     *
     * @return A 1-field tuple containing the number of inserted records, or
    * null if called more than once.
     * @see Database#getBufferPool
     * @see BufferPool#insertTuple
     */
    protected Tuple readNext()
            throws TransactionAbortedException, DbException {
        // some code goes here

        if( !this.dbIterator.hasNext() ){
            if( !isFirstCalled )  return null ;
        }

        int countResult = 0;
        while( this.dbIterator.hasNext() ) {
            try {
                Database.getBufferPool().insertTuple( this.transactionId , tableid , this.dbIterator.next() );
                countResult++ ;
            } catch (TransactionAbortedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        isFirstCalled = false ;
        resultTuple.setField(0 , new IntField(countResult) );

        return resultTuple ;
    }


}
